fix(install): drop podman as hard dependency for RPM installation#2137
fix(install): drop podman as hard dependency for RPM installation#2137pimlock wants to merge 11 commits into
Conversation
Remove Podman package and service coupling, rely on existing runtime detection, and surface actionable installer startup diagnostics. Document runtime prerequisites and VM packaging across install methods. Closes #2007 Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com>
|
🌿 Preview your docs: https://nvidia-preview-pr-2137.docs.buildwithfern.com/openshell |
Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com>
|
Addressed the documentation feedback in
|
Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com>
Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com>
Implemented proposal: runtime-neutral installation with gateway-owned detectionThe final implementation treats package installation and gateway health as separate outcomes while keeping optional compute runtimes outside OpenShell's ownership. Contract
Detection and guidance
Gateway startup now detects all available runtimes in Kubernetes → Podman → Docker priority order. On every automatic start it:
This gateway-level warning is necessary because the environment can change after installation. For example, adding Podman to a Docker-only host leaves the running gateway unchanged, but the next restart selects Podman unless Docker is pinned. Why this optionThe approach preserves the installation invariants: packages remain runtime-neutral, detection remains observational, user configuration remains explicit, and the gateway is never exposed beyond loopback without an operator action. The installer provides immediate discoverability, while gateway startup provides durable guidance for later environment changes. Alternatives explored
The final implementation combines the useful parts of the last two options: immediate installer guidance plus authoritative startup diagnostics, without automatic configuration changes. |
Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com>
Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com>
|
@maxamillion @drew this is now implemented as a runtime-neutral installation contract. Problem: a Docker-only RHEL host could not install OpenShell because the RPM required Podman. Implemented outcome:
The main installation invariants are: native package installation, CLI and gateway availability, a supervised user service, preserved user configuration, loopback/TLS defaults, no management of optional runtimes, explicit operator-owned driver pinning, and a clear split between package success and service health. We explored:
The selected design combines installer detection for immediate discoverability with gateway startup warnings for long-term correctness. This covers runtimes installed after OpenShell while keeping detection observational and all configuration changes explicit. |
Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com>
Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com>
|
|
||
| report_detected_compute_driver() { | ||
| _gateway_bin="${OPENSHELL_GATEWAY_BIN:-openshell-gateway}" | ||
| if ! _detected_driver="$(as_target_user "$_gateway_bin" config detect-driver)"; then |
There was a problem hiding this comment.
Not sure if exposing the detected driver just for this is worth it. Arguably it provides a slightly better UX, guiding the user, rather than requiring after-the-fact troubleshooting.
There was a problem hiding this comment.
Thinking out loud here. Instead of implementing this in a shell script, does it make sense to add something like an openshell check command? (out of scope for this PR though).
There was a problem hiding this comment.
I like this idea, this kind of diagnostics on the openshell side would make sense, maybe in the form of openshell-gateway doctor? Then that could detect the driver and run doctor on that? This way we only orchestrate the process of gathering info, but we don't need to understand specifics about the driver.
In this case the podman driver would check the config and output "you need to bind the gateway to 0.0.0.0, because you're using a rootless podman".
There was a problem hiding this comment.
In this case the podman driver would check the config and output
Yes, we can provide the feedback without trying to automate the broadening automatically.
Stop enumerating the VM driver libexec search paths in the RPM CONFIGURATION doc; defer to the driver_dir setting and the gateway's startup error, which lists the directories it actually searched. Correct the VM README (the single detailed source) to match the four paths the gateway searches. Align the QUICKSTART detection order with the other docs (Kubernetes, then Podman, then Docker) and drop the no-op bind-address reset from the config-set example. Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com>
| - Do not install, remove, start, or configure optional Docker and Podman | ||
| runtimes. |
There was a problem hiding this comment.
This is unrelated to this change, but currently the Docker driver will stop all sandboxes if the gateway is restarted (as it would be under upgrade).
| struct SetArgs { | ||
| /// Select one compute driver, or use `auto` to remove an existing pin. | ||
| #[arg(long, value_name = "DRIVER")] | ||
| compute_driver: Option<String>, | ||
|
|
||
| /// Set the gateway listener socket address. | ||
| #[arg(long = "bind-address", value_name = "IP:PORT")] | ||
| gateway_bind_address: Option<SocketAddr>, | ||
| } |
There was a problem hiding this comment.
Do we have to explicitly add options that we want to be able to set via the CLI? Would we be able to infer them from the toml keys?
There was a problem hiding this comment.
Good question.
I wanted to keep this one simple, with an idea that later we can add an option to support any arbitrary config field. But then there would be 2 ways of setting these 2 fields. I think we could support setting arbitrary keys right away, one thing to figure out would be arrays, specifically arrays of tables and what to support there (e.g. delete ith item?)
There was a problem hiding this comment.
Does supporting more complex operations like arrays of tables mean that we end up with a jq-like DSL?
As long as we don't block something like this with an initial implementation, we could limit the config set command to "regular" fields, and punt on deletion and insertion of table values?
| /// Gateway startup reads this file. Config subcommands update it. Gateway | ||
| /// command-line flags and `OPENSHELL_*` environment variables continue to | ||
| /// take precedence over file values at runtime. | ||
| #[arg(long, env = "OPENSHELL_GATEWAY_CONFIG", global = true)] |
There was a problem hiding this comment.
In the nvidia-ctk CLI I also implemented an nvidia-ctk config --set KEY=VALUE command. Here I had the default behaviour be that it prints the modified CONFIG (with --config specifying the path) to stdout by default and added an --in-place flag to update the specified input. Alternatively one could redirect to an arbitrary file.
| example, pin Docker: | ||
|
|
||
| ```shell | ||
| openshell-gateway config set --compute-driver docker |
There was a problem hiding this comment.
What if this were:
| openshell-gateway config set --compute-driver docker | |
| openshell-gateway config --set openshell.gateway.drivers=docker --in-place |
There was a problem hiding this comment.
Yeah, we could go that route! Similar comment: #2137 (comment)
Would config set make more sense than config --set? What other -- would the config have? Other parts of our CLI use the subcommands to describe a behavior and flags/params to provide input (e.g. policy set, inference set).
openshell-gateway config set openshell.gateway.drivers docker
# kubectl/gh uses this
# should be easier to provide completions
# only supports single value at a time? I think being able to atomically update multiple things in one command would be good.
openshell-gateway config set openshell.gateway.drivers=docker
# allows providing multiple values at a time
openshell-gateway config set --key openshell.gateway.drivers --value docker
# unnecessary verbosityThere was a problem hiding this comment.
I used config --set in nvidia-ctk because we were avoiding positional arguments in our CLI.
I would argue that setting multiple things atomically makes sense. With that in mind, using positional arguments makes sense:
openshell-gateway config set [KEY1=VALUE1] [KEY2=VALUE2]
There was a problem hiding this comment.
I updated the code to be something like:
config set 'openshell.gateway.drivers=["docker"]'
Note that the quoting is required now, because drivers is a list.
On the "in-place" edit, I think in most cases the intent is going to be to update the effective config, so I'm leaning towards not having --in-place flag for that (this is what tools like kubectl, gh, glab do).
Unless I'm misunderstanding something, this also seems to negate the purpose of using a package manager to begin with by sidestepping dependency management. The user installs the package which does not pull in a dependent runtime so the |
Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com>
|
Thanks for taking a look @maxamillion. This may be something better discussed during the call, so I will keep this brief. Btw I'm not sold on this solution and I don't have much experience in this space, so any feedback or guidance is appreciated. I will start with the original problem, so we can discuss the solution in that context. The original problem: user cannot install OpenShell on their system (Rocky 8, still supported until 2029). They already have docker installed and openshell installation fails when installing podman, which they don't want to use anyways. The outcome is: cannot install openshell because of that, at least not using the official script. It's still possible to install by downloading binaries manually.
I think having the package manager is still useful - it manages the artifacts, versions, checksums, removal, etc.
Yes, this is correct, the dependent runtime is a prerequisite in this model. This is already the case with deb and homebrew installation. I'd consider things like container engine to be of an host-level infrastructure, rather than user-space, so not bringing them in as part of application's dependency does make sense, especially that openshell can work with multiple of them. This may be an argument for making the VM driver the default, since that's more self-contained (but it's also limited - it requires nested virtualization). My sense is that installing a container engine together with openshell is a bit heavyweight and should be considered carefully. If we did go that route, I'd see it as something that the user needs to explicitly agree to, e.g. through a prompt in install script (if installing interactively) or a flag, e.g. Related to your point
we could make the driver not required on the gateway startup. Any operation requiring the driver would fail, but the gateway could be up. This would add complexity to driver management, it would get registered at the first successful interaction, etc. |
Thinking about this some more, maybe relying on podman by default is a good solution (assuming docker is not installed on the system) and the user doesn't explicitly opt-out? |
|
perhaps the rpm package could be split into a few packages that co-depends on the right backend dependency (docker, podman, etc) |
|
On the snap front we could have several components (cli, gateway) but once we split that so fine, I wonder what the openshell snap should then contain? |
Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com>
+1, that's definitely one of the options to consider. There is still a question how the option to install going to be decided. Right now we manage all the installations through the install script, we could add flags to it. Or we could publish artifacts to support native installation (e.g. There is also potential split into cli and gateway, so we could have: But now we need to reproduce this across all package managers for consistency. |
|
RPM and Den are similar and doing this split is not hard IMO In snaps the equivalent is to use components. they act like DLC in games. The install experience is a combination of the snap name and any number of components separated by + snap install openshell |
Summary
Make package installation runtime-neutral so installing OpenShell does not require Podman, Docker, or another optional compute runtime. The RPM no longer depends on Podman, package-managed gateways retain automatic driver selection, and the installer reports package installation and gateway health as separate outcomes.
This version keeps runtime detection inside the gateway.
install.shuses the read-only detection CLI for immediate guidance, while every gateway start logs the selected driver, all detected alternatives, multi-runtime pinning guidance, and the rootless Podman bind command when applicable.Related Issue
Closes #2007
Installation Invariants
openshellandopenshell-gatewayartifacts in the package manager's standard executable path.Changes
podman.socketordering from the RPM spec.127.0.0.1:17670.openshell-gateway config detect-driverwith stablekubernetes,podman,docker, ornoneoutput.install.shadvisory: it never changes driver selection or listener configuration.openshell-gateway config setwith repeatable dottedKEY=VALUEassignments for typed, validated, comment-preserving, atomic TOML updates.package installation succeededseparately fromgateway service is healthy.install.shand gateway diagnostics.Runtime Scenarios
install.shreturns nonzero with diagnostics. The service keeps retrying and can recover after a runtime is installed. Rootless Podman still requires the explicit bind change before sandboxes can call back.openshell-gateway config set 'openshell.gateway.compute_drivers=["<driver>"]'guidance.Why This Option
This design follows the invariants above: package installation stays independent of optional runtimes, configuration remains operator-owned and visible in TOML, loopback is never widened implicitly, and runtime changes after installation remain observable. Keeping the warning in the gateway is important because an installer-only warning cannot cover Docker or Podman installed later.
Automatic selection remains the zero-configuration recovery path. Explicit
config setcommands are the stability mechanism when an operator wants a fixed driver.Alternatives Explored
install.sh. Rejected because repository setup, rootless configuration, daemon lifecycle, licensing, and enterprise policy vary across supported systems.install.sh --compute-driver/OPENSHELL_INSTALL_COMPUTE_DRIVER. Implemented during exploration, then removed because it duplicated gateway configuration policy and made installation persist a driver choice.OPENSHELL_DRIVERSin service definitions. Rejected because environment values outrank TOML and make later config edits appear ineffective.0.0.0.0when Podman is detected. Rejected because runtime probing must not silently expose the gateway on host interfaces.install.sh. Insufficient because runtimes can be installed or removed after installation.detect-driverfor immediate Podman guidance.Testing
mise run pre-commitpassesmise run testpasses (included bymise run pre-commit)mise run cipasses (mise run pre-commitis thecialias)Focused coverage:
config setparsing, TOML value types, validation, and atomic multi-key updatesChecklist